package com.jtp7.demo.service.impl;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.jtp7.demo.aop.annotation.Log;
import com.jtp7.demo.asyn.TruckinfoAsynSave;
import com.jtp7.demo.entity.TruckInfo;
import com.jtp7.demo.entity.response.CommonCode;
import com.jtp7.demo.entity.dto.TruckInfoDTO;
import com.jtp7.demo.entity.response.PageListResult;
import com.jtp7.demo.entity.vo.AddTruckInfoDTO;
import com.jtp7.demo.exception.ExceptionCast;
import com.jtp7.demo.mapper.TruckInfoMapper;
import com.jtp7.demo.service.ICacheRedis;
import com.jtp7.demo.service.ITruckInfoService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;

import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author author
 * @since 2021-07-27
 */
@Slf4j
@Service
public class TruckInfoServiceImpl extends ServiceImpl<TruckInfoMapper,TruckInfo> implements ITruckInfoService {

    @Autowired
    private TruckInfoMapper truckInfoMapper;

    @Autowired
    private RedisTemplate<String,Object> redisTemplate;

    @Autowired
    private ICacheRedis<Object> cacheRedisTemplate;
    @Autowired
    private TruckinfoAsynSave truckinfoAsynSave;

    /**
     * redis添加缓存
     * @param truckInfoList
     */
    @Override
    public void cacheRedis(List<TruckInfo> truckInfoList) {
        long i = 10;
        cacheRedisTemplate.deletKey("info");
        for (TruckInfo truckInfo : truckInfoList) {
            i = i+50;
            cacheRedisTemplate.updtaRedis(truckInfo,i,truckInfo.getName(),truckInfo.getDrivingCode(),truckInfo.getPhone(),truckInfo.getId());
        }

    }


    /**
     * 添加司机条件
     *
     * @param addTruckInfoDTOList
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public Map<Object,Object> addCondition(List<AddTruckInfoDTO> addTruckInfoDTOList) {
        //如果是null或者数据是200条以上就抛出异常
        if (ObjectUtils.isEmpty(addTruckInfoDTOList) || addTruckInfoDTOList.size() >= 200) {
            ExceptionCast.cast(CommonCode.FAIL);
        }

        List<TruckInfo> infoList = new ArrayList<>();
         ArrayList<String> addOkTruckInfo = new ArrayList<>();
         for (AddTruckInfoDTO addTruckInfoDTO : addTruckInfoDTOList) {
            //判断司机是否出存在
            boolean isNull = this.drivingCodeIsNull(addTruckInfoDTO.getDrivingCode());
            if (isNull && addTruckInfoDTOList.size() <= 1) {
                ExceptionCast.cast(CommonCode.NO_ADD_TRUCKINFO);
            }
            if (isNull) {
                addOkTruckInfo.add(addTruckInfoDTO.getName());
                continue;
            }

            TruckInfo truckInfo = new TruckInfo();
            BeanUtils.copyProperties(addTruckInfoDTO, truckInfo);

            String code = this.getDrivingCodeAndAfterSix(truckInfo.getDrivingCode());
            truckInfo.setUsername(code);
            truckInfo.setVersion(0);

            infoList.add(truckInfo);
        }

         Map<Object,Object> map =   new HashMap<>();
         map.put("1", infoList);
         map.put("2",addOkTruckInfo);
        return map;
    }


    /**
     * 修改司机信息
     *
     * @return
     */
    @Override
    @Transactional(rollbackFor = {RuntimeException.class, Exception.class})
    public TruckInfoDTO update(TruckInfoDTO truckInfoDto) {
        if (ObjectUtils.isEmpty(truckInfoDto.getDrivingCode())) {
            ExceptionCast.cast(CommonCode.DRIVINGCODE_ISNULL);
        }


        TruckInfo truckInfoOne =  truckInfoMapper.selectById(truckInfoDto.getId());
        if (ObjectUtils.isEmpty(truckInfoOne) ||
                ObjectUtils.isEmpty(truckInfoOne.getDrivingCode()) ||
                ObjectUtils.isEmpty(truckInfoDto.getDrivingCode())) {
            ExceptionCast.cast(CommonCode.NO_TRUCKINFO);
        }

        //如果身份证号码一样就可以进行修改
        if (truckInfoOne.getDrivingCode().equals(truckInfoDto.getDrivingCode())) {
            TruckInfo truckInfo = new TruckInfo();
            BeanUtils.copyProperties(truckInfoDto, truckInfo);

            truckInfoMapper.update(truckInfo, null);

            //修改缓存
            this.cacheRedisTemplate.deletKey("info");
            this.cacheRedisTemplate.updtaRedis(truckInfo,3L,truckInfo.getDrivingCode(),truckInfo.getPhone(),truckInfo.getName(),truckInfo.getId());

            return truckInfoDto;
        } else {
            ExceptionCast.cast(CommonCode.NO_TRUCKINFO);
        }
        return null;
    }



    /**
     * 按司机姓名进行模糊搜索
     *
     * @param name
     * @return
     */
    @Override
    public PageListResult findByName(String name, String phone, String drivingCode, Integer currentPage, Integer size) {

        if(null == name  && null == phone && null == drivingCode && null == currentPage && null == size ) {
            String json = cacheRedisTemplate.getKey("info");
          //  String json = (String) redisTemplate.boundValueOps("info").get();
            if (!ObjectUtils.isEmpty(json)) {
                return JSONObject.parseObject(json, PageListResult.class);
            }
        }
        PageListResult<Object> truckInfoPageListResult = this.cacheRedisTemplate.redisFuzzySearchBeforeTo(currentPage, size,name, phone, drivingCode);

        if (!ObjectUtils.isEmpty(truckInfoPageListResult)) {
            return truckInfoPageListResult;
        }

        if (currentPage == null ) {
            currentPage = 1;
        }
        if (size == null ) {
            size = 8;
        }


        LambdaQueryWrapper<TruckInfo> wrapper = new LambdaQueryWrapper<>();
        if (!ObjectUtils.isEmpty(name) && !"name".equals(name)) {
            wrapper.like(TruckInfo::getName, name);
        }
        if (!ObjectUtils.isEmpty(phone) && !"phone".equals(phone)) {
            wrapper.like(TruckInfo::getPhone, phone);
        }
        if (!ObjectUtils.isEmpty(drivingCode) && !"drivingCode".equals(drivingCode)) {
            wrapper.like(TruckInfo::getDrivingCode, drivingCode);
        }

        Page<TruckInfo> page = truckInfoMapper.selectPage(new Page<>(currentPage, size), wrapper);
        PageListResult<TruckInfo> pageListResult = new PageListResult<>();
        pageListResult.setList( page.getRecords());
        pageListResult.setPages(page.getPages()+1);

        if(null == name  && null == phone && null == drivingCode && 1 == currentPage && 8 == size ) {
            String jsonPage = JSON.toJSONString(pageListResult);
            redisTemplate.boundValueOps("info").set(jsonPage);
        }

        //保存缓存异步
        String jsonString = JSONObject.toJSONString(pageListResult);
        //this.cacheRedisTemplate.redisFuzzySearchAfterTo(jsonString,currentPage,size,5L,name,phone,drivingCode);
       //this.asynSave(cacheRedisTemplate,jsonString,currentPage,size,5L,null,name,phone,drivingCode);
        TruckinfoAsynSave.asynSave2(cacheRedisTemplate,jsonString,currentPage,size,5L,null,name,phone,drivingCode);
        List<TruckInfo> records1 = page.getRecords();
        List<TruckInfo> records = new CopyOnWriteArrayList<>();
        records.addAll(records1);
        //异步保存缓存时更新id
        //this.asynSave(cacheRedisTemplate,null,currentPage,size,5L,records,name,phone,drivingCode);
        TruckinfoAsynSave.asynSave2(cacheRedisTemplate,null,currentPage,size,5L,records);
        System.out.println("异步结束--------"+"返回数据");
        return pageListResult;
    }

    //异步
    @Deprecated
    private void asynSave(ICacheRedis<Object> iCacheRedis,String jsonString, Integer currentPage, Integer size, long miss,List<TruckInfo> records, String ... info) {
        try {
            log.info("定时开始");
            // Thread.sleep(10L);
        } catch (Exception e) {
            e.printStackTrace();
        }

        if (ObjectUtils.isEmpty(records)) {

            new Thread(new Runnable() {
                @Override
                public void run() {
                    for (String s : info) {
                        iCacheRedis.redisFuzzySearchAfterTo(jsonString, currentPage, size, miss, s);
                    }
                }
            }).start();

           for (String s : info) {
                CompletableFuture.runAsync(() -> this.cacheRedisTemplate.redisFuzzySearchAfterTo(jsonString, currentPage, size, miss, s));

           }
           return;
       }
       //保存缓存时更新id
        new Thread(new Runnable() {
            @Override
            public void run() {
                for (TruckInfo record : records) {
                    log.info("异步开始");
                    String jsonString1 = JSONObject.toJSONString(record);
                    iCacheRedis.redisFuzzySearchAfterTo(jsonString1, currentPage, size, miss, record.getId());
                    CompletableFuture.runAsync(() ->{
                        iCacheRedis.redisFuzzySearchAfterTo(jsonString1, currentPage, size, miss, record.getId());
                    });
                    log.info("22222222222");
                }
            }
        }).start();
        for (TruckInfo record : records) {
            log.info("异步开始");
            String jsonString1 = JSONObject.toJSONString(record);

          CompletableFuture.runAsync(() ->{
              iCacheRedis.redisFuzzySearchAfterTo(jsonString1, currentPage, size, miss, record.getId());
          });
            log.info("22222222222");
        }

    }



    /**
     * 查询司机状态为在岗的信息
     *
     * @param version
     * @return
     */
    @Override
    public List<TruckInfo> findByVersion(int version) {

        LambdaQueryWrapper<TruckInfo> truckInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        truckInfoLambdaQueryWrapper.eq(TruckInfo::getVersion, version);
        return truckInfoMapper.selectList(truckInfoLambdaQueryWrapper);
    }

    /**
     * 截取身份证后6位
     *
     * @param drivingcode
     * @return
     */
    private String getDrivingCodeAndAfterSix(String drivingcode) {
        return drivingcode.substring(drivingcode.length() - 6);
    }

    /**
     * 是否身份证已存在
     *
     * @param drivingCode
     * @return
     */
    private boolean drivingCodeIsNull(String drivingCode) {
        LambdaQueryWrapper<TruckInfo> truckInfoLambdaQueryWrapper = new LambdaQueryWrapper<>();
        truckInfoLambdaQueryWrapper.eq(TruckInfo::getDrivingCode, drivingCode);
        Integer integer = truckInfoMapper.selectCount(truckInfoLambdaQueryWrapper);

        return integer >0;
    }

}
